
package com.atguigu.bigdata.spark.rdd.operate;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;

import java.util.Arrays;
import java.util.List;

public class Spark02_Operate_Transform_Map_7 {

    public static void main(String[] args) {
        final SparkConf conf = new SparkConf();
        conf.setMaster("local[2]");
        conf.setAppName("spark");
        final JavaSparkContext jsc = new JavaSparkContext(conf);

        final JavaRDD<Integer> rdd = jsc.parallelize(Arrays.asList(1, 2, 3, 4), 2);

        final JavaRDD<Integer> newRDD1 = rdd.map(
                num -> {
                    System.out.println("@@@" + num);
                    return num;
                }
        );

        final JavaRDD<Integer> newRDD2 = newRDD1.map(
                num -> {
                    System.out.println("###" + num);
                    return num;
                }
        );

        newRDD2.collect();
        jsc.close();
    }

    /**
     * 并行计算：
     *
     * Spark的设计目标是高效处理大规模数据集，它会尽可能将计算分布到多个计算单元（如CPU核心）上执行。在这段代码中，conf.setMaster("local[2]")指定了运行环境为本地模式，并使用两个线程执行任务（local[2] 表示使用2个线程）。因此，当Spark在运行时，会将RDD的各个分区分配给不同的线程并行处理。
     * RDD的分区：
     *
     * 在代码中，rdd.parallelize(Arrays.asList(1, 2, 3, 4), 2) 将列表 [1, 2, 3, 4] 转换成了一个包含2个分区的RDD。假设分区是这样划分的：
     * 分区1：包含元素 [1, 2]
     * 分区2：包含元素 [3, 4]
     * map 操作：
     *
     * 当你对RDD进行 map 操作时，Spark会在每个分区上独立执行这个操作。由于两个分区是在两个线程上并行执行的，因此 map 操作中的 System.out.println() 语句的执行顺序可能是交错的。
     * 结果分析：
     *
     * 在第一次 map 操作中（打印 @@@num），两个分区被不同的线程处理，因此打印的顺序可能是交错的，具体的顺序取决于哪个线程先完成任务。
     * 在第二次 map 操作中（打印 ###num），每个分区中的元素同样被独立处理，并且因为 map 操作是惰性求值的（lazy evaluation），直到 newRDD2.collect() 被调用时，所有的计算才被触发。
     *
     * 因为Spark的并行计算和RDD的分区导致了输出顺序的非确定性。不同的线程处理不同的分区，线程的执行顺序并不固定，所以你看到了交错的输出顺序。这种行为在并行计算中是正常的。
     */
}
